package com.pay.web.utils;

/**
 * Created by chenweiyi on 2018/1/31.
 */
import com.pay.request.SignType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.util.*;
import java.beans.BeanInfo;
public final class WebUtils {

    private static Logger logger = LoggerFactory.getLogger(WebUtils.class);

    /**
     *  获取请求参数
     * @param request
     * @return
     */
    public static Map<String,Object> getRequestParameterMap(HttpServletRequest request){
        Map<String,Object> result = new HashMap<String,Object>();
        Map<String,String[]>  parameterMap = request.getParameterMap();
        Iterator<Map.Entry<String,String[]>> iterator = parameterMap.entrySet().iterator();
        while(iterator.hasNext()){
           Map.Entry<String,String[]> entry = iterator.next();
            String key = entry.getKey();
            String [] values = entry.getValue();
            if(values != null && values.length > 0){
                if(values.length == 1){
                    result.put(key,values[0]);
                }else{
                    List<String> list =  Arrays.asList(values);
                    result.put(key,list);
                }
            }
        }
        return result;
    }

    /**
     * 获取请求参数
     * @param request
     * @return
     */
    public static Map<String,String> getRequestParameter(HttpServletRequest request){
        Map<String,String> result = new HashMap<String,String>();
        Map<String,String[]>  parameterMap = request.getParameterMap();
        Iterator<Map.Entry<String,String[]>> iterator = parameterMap.entrySet().iterator();
        while(iterator.hasNext()){
            Map.Entry<String,String[]> entry = iterator.next();
            String key = entry.getKey();
            String [] values = entry.getValue();
            if(values != null && values.length > 0){
                if(values.length == 1){
                    result.put(key,values[0]);
                }
            }
        }
        return result;
    }




    /**
     * 集合转换为对象
     * @param map
     * @param o
     * @param <T>
     * @return
     * @throws Exception
     */
    public static <T> T  mapToObject(Map<String,Object> map, Class<T> o)throws Exception{
        if(map == null){
            return null;
        }
        Object object = o.newInstance();
        BeanInfo beanInfo = Introspector.getBeanInfo(o);
        PropertyDescriptor [] descriptors = beanInfo.getPropertyDescriptors();
        for(int i = 0;i < descriptors.length;i++){
            PropertyDescriptor descriptor = descriptors[i];
            Method setter =  descriptor.getWriteMethod();
            if(setter != null){
               Object value =  map.get(descriptor.getName());
               if(value != null){
                   setter.invoke(object,String.valueOf(value));
               }
            }
        }
        return (T)object;
    }

    /**
     * 对象转集合
     * @param object
     * @return
     */
    public static Map<String,Object> objectToMap(Object object){

        Map<String,Object> map = new HashMap<String,Object>();
        Class<?> clazz = object.getClass();
        try {
            for(Field field :clazz.getDeclaredFields()){
                field.setAccessible(true);
                String key = field.getName();
                Object value = field.get(object);
                map.put(key, value);
            }
        }catch(Exception e){
            logger.error(e.getMessage());
        }
        return map;
    }

    public static boolean isEmpty(String str){
        if(str == null || str.trim().isEmpty()) return true;
        return  false;
    }

    /**
     * 编码URI
     * @param uri
     * @return
     */
    public static String encodeURI(String uri){
        String encoded = null;
        if(uri != null){
            try{
                encoded = URLEncoder.encode(uri,Constants.CHARSET);
            }catch (Exception e){
                logger.error("Encode Uri :{}" , e);
            }
        }
        return encoded;
    }

    /**
     * 解码uri
     * @param uri
     * @return
     */
    public static String decodeURI(String uri){

        String decoded  = null;
        if(uri != null){
            try{
                decoded = URLDecoder.decode(uri,Constants.CHARSET);
            }catch(Exception e){
                logger.error("Decode Uri :{}" , e);
            }
        }
        return decoded;
    }

    /**
     * 获取客户端ip
     * @param request
     * @return
     */
    public static String getClientIp(HttpServletRequest request){
        String ip = request.getHeader("X-Forwarded-For");
        if(isEmpty(ip) || "unknown".equalsIgnoreCase(ip)){
            ip = request.getHeader("Proxy-Client-IP");
        }
        if(isEmpty(ip) || "unknown".equalsIgnoreCase(ip)){
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if(isEmpty(ip) || "unknown".equalsIgnoreCase(ip)){
            ip = request.getHeader("X-Real-IP");
        }
        if(isEmpty(ip) || "unknown".equalsIgnoreCase(ip)){
            ip = request.getHeader("PROXY_FORWARDED_FOR");
        }
        if(isEmpty(ip) || "unknown".equalsIgnoreCase(ip)){
            ip = request.getRemoteAddr();
            if(ip.equals("127.0.0.1") || ip.equals("0:0:0:0:0:0:0:1")){
                try{
                    InetAddress address = InetAddress.getLocalHost();
                    ip = address.getHostAddress();
                    if(ip != null && ip.length() > 15 && ip.indexOf(",") > 0){
                        ip = ip.substring(0,ip.indexOf(","));
                    }
                }catch(Exception e){

                }
            }
        }
        return ip;
    }


    /**
     * 将流转换为字符串
     * @param stream
     * @return
     */
    public static String parseStreamToStr(InputStream stream){

        if(stream == null) return null;
        InputStreamReader reader = new InputStreamReader(stream, Charset.forName("utf-8"));
        BufferedReader r = new BufferedReader(reader);
        StringBuilder builder = new StringBuilder();
        try {
            String line;
            while(( line = r.readLine())!= null){
                builder.append(line);
            }
        }catch (Exception e){
            logger.error("{}",e);
        }finally {
            try{
                r.close();
            }catch (Exception e){
                logger.error("{}",e);
            }
        }
        return builder.toString();
    }

    /**
     * 对象转字符串
     * @param object
     * @return
     */
    public static String objectToString(Object object){
        if(object == null) return null;
        return String.valueOf(object);
    }

    /**
     * 字节数组转为16进制
     * @param bytes
     * @return
     */
    public static String byteArrayToHex(byte [] bytes){
        StringBuffer buffer = new StringBuffer();
        for(byte by : bytes){
            buffer.append(Integer.toHexString( (by & 0xff) | 0x100).substring(1,3));
        }
        return buffer.toString();
    }


    /**
     * md5加密
     * @param data
     * @return
     */
    public static String md5(String data){

        try{
            MessageDigest digest = MessageDigest.getInstance("MD5");
            byte []  bytes =digest.digest(data.getBytes("UTF-8"));
            return byteArrayToHex(bytes).toUpperCase();
        }catch(Exception e){
            logger.error(e.getMessage());
        }
        return null;
    }



    /**
     * HMAC-SHA256加密
     * @param data
     * @param key
     * @return
     */
    public static String hmac_sha256(String data,String key){
        try{
            Mac mac = Mac.getInstance("HmacSHA256");
            SecretKeySpec spec = new SecretKeySpec(key.getBytes("UTF-8"),"HmacSHA256");
            mac.init(spec);
            byte [] bytes = mac.doFinal(data.getBytes("UTF-8"));
            return byteArrayToHex(bytes).toUpperCase();
        }catch(Exception e){
            logger.error(e.getMessage());
        }
        return null;
    }

    /**
     *
     * 签名
     * @param object
     * @param key
     * @param signType
     * @return
     */
    public static String signature(Object object,String key,SignType signType){
        try{
            Map<String,Object> map = objectToMap(object);
            return signature(map,key,signType);
        }catch(Exception e){
            logger.error(e.getMessage());
        }
        return null;
    }

    /**
     * 签名
     * @param map
     * @param key
     * @param signType
     * @return
     */
    public static String signature(Map<String,Object> map,String key,SignType signType){

        Set<String>  set = map.keySet();
        String [] keys = set.toArray(new String [set.size()]);
        Arrays.sort(keys);
        StringBuilder builder = new StringBuilder();
        for(String k : keys){
            if(k.equals("signature")){
                continue;
            }
            Object value = map.get(k);
            if(value != null && !value.equals("")){
                builder.append(k)
                        .append("=")
                        .append(value)
                        .append("&");
            }
        }
        builder.append("key=").append(key);
        logger.info("signature data : {}",builder.toString());
        if(SignType.md5.equals(signType)){
            return md5(builder.toString());
        }else if(SignType.hmacsha256.equals(signType)){
            return hmac_sha256(builder.toString(),key);
        }
        return null;

    }

     public static void main(String [] args){
         System.out.println(md5("中"));
     }

}
